package com.zhentao.device.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhentao.pojo.WaterQualityAnomaly;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 告警 WebSocket 处理器
 * 处理实时告警推送
 */
@Component
@ServerEndpoint("/ws/alerts/{userId}")
public class AlertWebSocketHandler {

    // 存储所有连接的会话
    private static final CopyOnWriteArraySet<Session> sessions = new CopyOnWriteArraySet<>();
    
    // 存储用户会话映射
    private static final Map<String, Session> userSessions = new ConcurrentHashMap<>();
    
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 连接建立时调用
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        sessions.add(session);
        System.out.println("🔌 WebSocket连接已建立，用户ID: " + userId + "，当前连接数: " + sessions.size());
        
        // 将用户ID存储到会话属性中
        session.getUserProperties().put("userId", userId);
        
        // 发送连接成功消息
        Map<String, Object> userData = new HashMap<>();
        userData.put("userId", userId);
        sendMessage(session, createMessage("connected", "WebSocket连接成功", userData));
    }

    /**
     * 收到客户端消息时调用
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            System.out.println("📨 收到WebSocket消息: " + message);
            
            // 解析消息
            Map<String, Object> messageData = objectMapper.readValue(message, Map.class);
            String type = (String) messageData.get("type");
            
            switch (type) {
                case "subscribe":
                    // 订阅告警推送
                    String userId = (String) messageData.get("userId");
                    if (userId != null) {
                        userSessions.put(userId, session);
                        System.out.println("👤 用户 " + userId + " 订阅告警推送");
                    }
                    break;
                case "unsubscribe":
                    // 取消订阅
                    String unsubUserId = (String) messageData.get("userId");
                    if (unsubUserId != null) {
                        userSessions.remove(unsubUserId);
                        System.out.println("👤 用户 " + unsubUserId + " 取消订阅告警推送");
                    }
                    break;
                case "ping":
                    // 心跳检测
                    sendMessage(session, createMessage("pong", "pong", null));
                    break;
                default:
                    System.out.println("❓ 未知消息类型: " + type);
            }
        } catch (Exception e) {
            System.err.println("❌ 处理WebSocket消息失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 连接关闭时调用
     */
    @OnClose
    public void onClose(Session session) {
        sessions.remove(session);
        
        // 从用户会话映射中移除
        String userId = (String) session.getUserProperties().get("userId");
        if (userId != null) {
            userSessions.remove(userId);
            System.out.println("👤 用户 " + userId + " 已断开连接");
        }
        
        System.out.println("🔌 WebSocket连接已关闭，当前连接数: " + sessions.size());
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.err.println("🚨 WebSocket发生错误: " + error.getMessage());
        error.printStackTrace();
        
        // 移除有问题的会话
        sessions.remove(session);
        userSessions.entrySet().removeIf(entry -> entry.getValue().equals(session));
    }

    /**
     * 广播新告警给所有连接的客户端
     */
    public static void broadcastNewAlert(WaterQualityAnomaly alert) {
        System.out.println("📡 开始广播新告警: " + alert.getAnomalyId() + " - " + alert.getIndicatorCode());
        Map<String, Object> message = createAlertMessage("new_alert", alert);
        System.out.println("📡 告警消息内容: " + message);
        broadcastToAll(message);
        System.out.println("📡 告警广播完成，当前连接数: " + sessions.size());
    }

    /**
     * 广播告警状态更新给所有连接的客户端
     */
    public static void broadcastAlertUpdate(Long alertId, Integer status, String handlerId) {
        Map<String, Object> updateData = new HashMap<>();
        updateData.put("alertId", alertId);
        updateData.put("status", status);
        updateData.put("handlerId", handlerId);
        updateData.put("updateTime", System.currentTimeMillis());
        
        Map<String, Object> message = createMessage("alert_update", "告警状态已更新", updateData);
        broadcastToAll(message);
    }

    /**
     * 广播告警统计更新
     */
    public static void broadcastStatsUpdate(Map<String, Integer> stats) {
        Map<String, Object> message = createMessage("stats_update", "告警统计已更新", stats);
        broadcastToAll(message);
    }

    /**
     * 向指定用户发送消息
     */
    public static void sendToUser(String userId, Map<String, Object> message) {
        Session session = userSessions.get(userId);
        if (session != null && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(convertToJson(message));
            } catch (IOException e) {
                System.err.println("❌ 发送消息给用户 " + userId + " 失败: " + e.getMessage());
            }
        }
    }

    /**
     * 向所有连接的客户端广播消息
     */
    public static void broadcastToAll(Map<String, Object> message) {
        String jsonMessage = convertToJson(message);
        System.out.println("📡 准备广播JSON消息: " + jsonMessage);
        
        int successCount = 0;
        for (Session session : sessions) {
            if (session.isOpen()) {
                try {
                    session.getBasicRemote().sendText(jsonMessage);
                    successCount++;
                    System.out.println("✅ 消息已发送到会话: " + session.getId());
                } catch (IOException e) {
                    System.err.println("❌ 广播消息失败: " + e.getMessage());
                }
            } else {
                System.out.println("⚠️ 会话已关闭: " + session.getId());
            }
        }
        System.out.println("📡 广播完成，成功发送到 " + successCount + " 个客户端");
    }

    /**
     * 向指定会话发送消息
     */
    private void sendMessage(Session session, Map<String, Object> message) {
        try {
            session.getBasicRemote().sendText(convertToJson(message));
        } catch (IOException e) {
            System.err.println("❌ 发送消息失败: " + e.getMessage());
        }
    }

    /**
     * 创建告警消息
     */
    private static Map<String, Object> createAlertMessage(String type, WaterQualityAnomaly alert) {
        Map<String, Object> alertData = new HashMap<>();
        alertData.put("alertId", alert.getAnomalyId());
        alertData.put("deviceId", alert.getDeviceId());
        alertData.put("dataId", alert.getDataId());
        alertData.put("indicator", alert.getIndicatorCode());
        alertData.put("currentValue", alert.getCurrentValue());
        alertData.put("normalRange", alert.getNormalRange());
        alertData.put("anomalyType", alert.getAnomalyType());
        alertData.put("severity", alert.getSeverity());
        alertData.put("status", alert.getHandleStatus());
        alertData.put("createTime", alert.getCreateTime() != null ? alert.getCreateTime().getTime() : null);
        
        return createMessage(type, "新告警", alertData);
    }

    /**
     * 创建标准消息格式
     */
    private static Map<String, Object> createMessage(String type, String message, Object data) {
        Map<String, Object> messageMap = new HashMap<>();
        messageMap.put("type", type);
        messageMap.put("message", message);
        messageMap.put("data", data);
        messageMap.put("timestamp", System.currentTimeMillis());
        return messageMap;
    }

    /**
     * 将消息转换为JSON字符串
     */
    private static String convertToJson(Map<String, Object> message) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(message);
        } catch (Exception e) {
            System.err.println("❌ 转换JSON失败: " + e.getMessage());
            return "{}";
        }
    }

    /**
     * 获取当前连接数
     */
    public static int getConnectionCount() {
        return sessions.size();
    }

    /**
     * 获取当前用户数
     */
    public static int getUserCount() {
        return userSessions.size();
    }
}
